package com.app.teadoor.util;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.os.CountDownTimer;
import android.text.TextUtils;

import com.app.teadoor.basis.BasisActivity;
import com.app.teadoor.basis.BasisApp;
import com.app.teadoor.basis.Constants;
import com.app.teadoor.bluetooth.SearchBlueToothActivity;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.utils.BleLog;
import com.clj.fastble.utils.HexUtil;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import my.ActivityTool;
import my.LogUtil;
import my.MySharedPreferences;

public class BluetoothUtils {

    public static final String TAG = "BluetoothUtils";
    private static final int TIME_CONNECT_PAST = 30 * 1000;
    private static final int TIME_SEND_PAST = 30 * 1000;
    private static final int TIME_UPLOAD_PAST = 60 * 1000;
    private static final int TIME_UPLOAD_ONETIME_PAST = 15 * 1000;

    private static BluetoothUtils bluetoothUtils;

    private BleDevice mBleDevice;
    private MyBleConnectListener myBleConnectListener;
    private CountDownTimer mCountDownTimer;
    private long time_last_send = 0;
    private StringBuffer mStringBuffer;
    private List<Byte> mListByte;
    private boolean isConnect = false;
    MySendListener myListener;

    private BluetoothUtils() {
        BleManager.getInstance().setReConnectCount(0);

    }

    public static BluetoothUtils getInstance() {
        if (bluetoothUtils != null) return bluetoothUtils;
        bluetoothUtils = new BluetoothUtils();
        return bluetoothUtils;
    }


    public void connectDevice(BleDevice device, MyBleConnectListener listener) {
        LogUtil.i(TAG, "ConnectDevice---开始连接设备----》"+device.getName());

        this.mBleDevice = device;
        stopConnectDevice();
        this.myBleConnectListener = listener;
        BleManager.getInstance().connect(mBleDevice, mBleGattCallback);
    }

    private BleGattCallback mBleGattCallback = new BleGattCallback() {
        @Override
        public void onStartConnect() {
            LogUtil.i(TAG, "onStartConnect----》");
            stopCountDown();
            mCountDownTimer = new CountDownTimer(TIME_CONNECT_PAST, 1000) {
                @Override
                public void onTick(long l) {
                }

                @Override
                public void onFinish() {
                    LogUtil.i(TAG, "ConnectDevice---onTimeout-》");
                    if (myBleConnectListener != null)
                        myBleConnectListener.onTimeout();
                }
            };
            mCountDownTimer.start();
        }

        @Override
        public void onConnectFail(BleDevice bleDevice, BleException exception) {
            stopCountDown();
            if (myBleConnectListener != null)
//                myBleConnectListener.onFailed();
                 myBleConnectListener.onFailed(exception);
            LogUtil.i(TAG, "onConnectFail----->" + exception.toString());
        }

        @Override
        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
            LogUtil.i(TAG, "onConnectSuccess--->" + bleDevice.getName());
            BleLog.d("message=====   连接成功");
            EventBus.getDefault().post(new MyEvent(MyEvent.EVENT_TYPE_CONNECT));
            stopCountDown();
            saveCacheBleDevice();
            myBleConnectListener.onSuccess(bleDevice);
            mBleDevice = bleDevice;
            isConnect = true;

        }

        @Override
        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
            LogUtil.i(TAG, "onDisConnected--->" + device.getName());
            if(mBleDevice != null && mBleDevice.getMac().equals(device.getMac()) && isConnect){
                BleManager.getInstance().clearCharacterCallback(device);
                EventBus.getDefault().post(new MyEvent(MyEvent.EVENT_TYPE_DISCONNECT));
            }
            isConnect = false;
        }
    };

    public void sendAndNotify(byte[] sendDate,MySendListener bleSendListener) {
        LogUtil.i(TAG, "sendAndNotify--->");
        myListener = bleSendListener;
        stopCountDown();
        mCountDownTimer = new CountDownTimer(TIME_SEND_PAST, 1000) {
            @Override
            public void onTick(long l) {
            }
            @Override
            public void onFinish() {
                LogUtil.d(TAG, "sendAndNotify");
                if (myListener != null)
                    myListener.onTimeout();
            }
        };
        mCountDownTimer.start();
        mListByte = new ArrayList<>();
        notify(new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                write(sendDate, new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        if (current == total) {
                            LogUtil.d(TAG, "sendAndNotify onWriteSuccess");
                        }
                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        LogUtil.d(TAG, "sendAndNotify  == onWriteFailure");
                        if (myListener != null) {
                            myListener.onFailure("onWriteFailure");
                        }
                        stopCountDown();
                        stopNotify();
                    }
                });

            }

            @Override
            public void onNotifyFailure(BleException exception) {
                LogUtil.d(TAG, "sendAndNotify ------>onNotifyFailure");
                if (myListener != null) {
                    myListener.onFailure("onNotifyFailure");
                }
                stopCountDown();
                stopNotify();
            }

            @Override
            public void onCharacteristicChanged(byte[] data) {
//                LogUtil.d(TAG,"getATShow------>onCharacteristicChanged");
                for (Byte a : data) {
                    mListByte.add(a);
                }

//                String sMes = Analysis.ByteArrayToStr(mListByte);
                String sMes = Analysis.getByteToString(data);
                LogUtil.d(TAG,"获取到的数据==="+sMes);
                if (sMes != null && sMes.trim().length() > 0) {
                        LogUtil.d(TAG, "sendAndNotify------>onCharacteristicChanged----OK");
                        stopNotify();
                        stopCountDown();
                        if (myListener != null) {
                            myListener.onSuccess(sMes);
                        }
                }
            }
        });
    }


    public void startWarning() {
        LogUtil.i(TAG, "startWarning--->");
        write(Analysis.getBytes("B"), new BleWriteCallback() {
            @Override
            public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                if (current == total) {
                    LogUtil.d(TAG, "sendAndNotify onWriteSuccess");
                }
            }

            @Override
            public void onWriteFailure(final BleException exception) {
                LogUtil.d(TAG, "sendAndNotify  == onWriteFailure");
                if (myListener != null) {
                    myListener.onFailure("onWriteFailure");
                }
            }
        });
    }

    public void stopWarning() {
        LogUtil.i(TAG, "startWarning--->");
        write(Analysis.getBytes("N"), new BleWriteCallback() {
            @Override
            public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                if (current == total) {
                    LogUtil.d(TAG, "sendAndNotify onWriteSuccess");
                }
            }

            @Override
            public void onWriteFailure(final BleException exception) {
                LogUtil.d(TAG, "sendAndNotify  == onWriteFailure");
                if (myListener != null) {
                    myListener.onFailure("onWriteFailure");
                }
            }
        });
    }



    public void notify(BleNotifyCallback bleNotifyCallback) {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().notify(
                mBleDevice,
                Constants.DATA_TRANSMISSION,
                Constants.SERVICE_EIGENVALUE_READ,
                bleNotifyCallback
        );
    }

    public void stopNotify() {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().stopNotify(mBleDevice, Constants.DATA_TRANSMISSION, Constants.SERVICE_EIGENVALUE_READ);
    }

    private void notifyConnect(BleNotifyCallback bleNotifyCallback) {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().notify(
                mBleDevice,
                Constants.DATA_TRANSMISSION,
                Constants.SERVICE_EIGENVALUE_READ,
                bleNotifyCallback
        );
    }

    public void setMtu(int mtu,BleMtuChangedCallback bleMtuChangedCallback){
        BleManager.getInstance().setMtu(mBleDevice, mtu, bleMtuChangedCallback);
    }

    BleWriteCallback mBleWriteCallback = new BleWriteCallback() {
        @Override
        public void onWriteSuccess(int current, int total, byte[] justWrite) {
            LogUtil.i(TAG,"onWriteSuccess");
        }

        @Override
        public void onWriteFailure(BleException exception) {
            LogUtil.i(TAG,"onWriteFailure");
        }
    };

    public void write(String hexAction, BleWriteCallback bleWriteCallback) {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().write(
                mBleDevice,
                Constants.DATA_TRANSMISSION,
                Constants.SERVICE_EIGENVALUE_SEND,
                HexUtil.hexStringToBytes(hexAction),
                bleWriteCallback);
        time_last_send = new Date().getTime();
    }
    public void write(byte[] bytes, BleWriteCallback bleWriteCallback) {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().write(
                mBleDevice,
                Constants.DATA_TRANSMISSION,
                Constants.SERVICE_EIGENVALUE_SEND,
                bytes,
                bleWriteCallback);
        time_last_send = new Date().getTime();
    }
    public void write(byte[] bytes) {
        if (mBleDevice == null) {
            return;
        }
        BleManager.getInstance().write(
                mBleDevice,
                Constants.DATA_TRANSMISSION,
                Constants.SERVICE_EIGENVALUE_SEND,
                bytes,
                mBleWriteCallback);

        time_last_send = new Date().getTime();

    }

    public BleDevice getCacheBleDevice() {
        String mac = new MySharedPreferences(BasisApp.mContext).getString("bledevice_mac");
        if (TextUtils.isEmpty(mac)) return null;
        BluetoothDevice bluetoothDevice = BleManager.getInstance().getBluetoothAdapter().getRemoteDevice(mac);
        if (bluetoothDevice == null) return null;
        BleDevice bleDevice = new BleDevice(bluetoothDevice, 0, null, 0);
        return bleDevice;
    }

    public void saveCacheBleDevice() {
        if (mBleDevice == null) return;
        new MySharedPreferences(BasisApp.mContext).putString("bledevice_mac", mBleDevice.getMac());
    }

    public void stopConnectDevice() {
        if (mBleGattCallback != null) {
            if (mBleDevice != null) {
                BleManager.getInstance().removeConnectGattCallback(mBleDevice);
            }
//            mBleGattCallback = null;
        }
//        BleManager.getInstance().disconnectAllDevice();
    }

    public void reconect(BasisActivity activity) {
        connectDevice(mBleDevice, new MyBleConnectListener() {
            @Override
            public void onSuccess(BleDevice bleDevice) {
            }


            @Override
            public void onFailed(BleException exception) {
                activity.showToast("蓝牙连接失败错误码："+ exception.getCode());
            }
            @Override
            public void onTimeout() {
                activity.showToast("蓝牙连接超时");
            }
        });
    }

    public void stopCountDown() {
        if (mCountDownTimer != null) mCountDownTimer.cancel();
    }


    public QMUIDialog showReconnectDialog(BasisActivity mContext) {
        QMUIDialog.MessageDialogBuilder builder = new QMUIDialog.MessageDialogBuilder(mContext);
        builder.setMessage("蓝牙连接已断开！").addAction("取消", new QMUIDialogAction.ActionListener() {
            @Override
            public void onClick(QMUIDialog dialog, int index) {
                dialog.dismiss();
            }
        }).addAction("重新连接", new QMUIDialogAction.ActionListener() {
            @Override
            public void onClick(QMUIDialog dialog, int index) {
                if(mBleDevice ==null){
                    ActivityTool.skipActivity(mContext, SearchBlueToothActivity.class);
                    return;
                }
                mContext.showLoading("正在重新连接蓝牙设备");
                connectDevice(mBleDevice, new MyBleConnectListener() {
                    @Override
                    public void onSuccess(BleDevice bleDevice) {
                        mContext.showToast("蓝牙连接成功");
                        mContext.dismissProgress();
                        dialog.dismiss();
                    }


                    @Override
                    public void onFailed(BleException exception) {
                        mContext.showToast("蓝牙连接失败错误码："+ exception.getCode());
                        mContext.hideLoading();
                    }

                    @Override
                    public void onTimeout() {
                        mContext.showToast("蓝牙连接超时");
                        mContext.hideLoading();
                    }
                });
            }
        });
        QMUIDialog dialog = builder.create();
        dialog.show();
        return dialog;
    }

    public boolean checkConnect(){
        return isConnect;
    }
    public boolean checkConnectAndShowDialog(BasisActivity activity){
        if(!isConnect){
            showReconnectDialog(activity);
        }
        return isConnect;
    }

    public BleDevice getBleDevice() {
        return mBleDevice;
    }

    public void setBleDevice(BleDevice mBleDevice) {
        this.mBleDevice = mBleDevice;
    }

    public boolean isConnect() {
        return isConnect;
    }

    public void setConnect(boolean connect) {
        isConnect = connect;
    }

    public void logout(){
        if(mBleDevice == null)return;
//        BleManager.getInstance().removeConnectGattCallback(mBleDevice);//
        BleManager.getInstance().disconnect(mBleDevice);
        mBleDevice = null;
        isConnect = false;
    }


    public interface MySendListener {
        void onFailure(String message);

        void onSuccess(String result);

        void onTimeout();
    }

    public interface MyBleConnectListener {
        void onSuccess(BleDevice bleDevice);

        void onFailed(BleException exception);
        void onTimeout();

    }




}
